#include "base_globals.h"
#include "base_log.h"
#include <windows.h>
#include <stdio.h>
#include <stdarg.h>

EBaseError log_init(BaseLog* log)
{
    wchar_t wpath[MAX_PATH];
    int writtenSize = MultiByteToWideChar(CP_ACP, 0, log->path, -1, wpath, MAX_PATH);
    if (writtenSize <0) {
        return BASE_LOG_INIT_FAILED;
    }
    log->handle = CreateFileW(wpath, FILE_APPEND_DATA ,
        FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (log->handle == NULL) {
        return BASE_LOG_INIT_FAILED;
    }
    return BASE_SUCCEED;
}

void log_fini(BaseLog* log)
{
    if (log->handle != NULL) {
        CloseHandle((HANDLE)log->handle);
        log->handle = NULL;
    }
}

EBaseError log_info(uchar8* format, ...)
{
    uchar8 buffer[BASE_MAX_LOG_ENTRY_LENGHT];
    va_list args;
    va_start(args, format);
    vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, format, args); 
    va_end(args);
    return log(LOG_INFO, buffer);
}

EBaseError log_warn(uchar8* format, ...)
{
    uchar8 buffer[BASE_MAX_LOG_ENTRY_LENGHT];
    va_list args;
    va_start(args, format);
    vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, format, args); 
    va_end(args);
    return log(LOG_WARN, buffer);
}

EBaseError log_error(uchar8* format, ...)
{
    uchar8 buffer[BASE_MAX_LOG_ENTRY_LENGHT];
    va_list args;
    va_start(args, format);
    vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, format, args); 
    va_end(args);
    return log(LOG_ERROR, buffer);
}

EBaseError log_debug(uchar8* format, ...)
{
    uchar8 buffer[BASE_MAX_LOG_ENTRY_LENGHT];
    va_list args;
    va_start(args, format);
    vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, format, args); 
    va_end(args);
    return log(LOG_DEBUG, buffer);
}

EBaseError log(EBaseLogLevel level, uchar8* msg)
{
    uchar8 buffer[BASE_MAX_LOG_ENTRY_LENGHT*2] = {0};
    DWORD writtenBytes = 0;
    BOOL ret = TRUE;
    size_t length = 0;
    HANDLE handle = (HANDLE)globals()->log.handle;
    char* level_string = NULL;
    Globals* g = globals();
    if (g->conf.log_level < level) {
        return BASE_SUCCEED;
    }
    switch (level) {
        case LOG_INFO:
            level_string = "INFO  |";
            break;
        case LOG_WARN:
            level_string = "WARN  |";
            break;
        case LOG_ERROR:
            level_string = "ERROR |";
            break;
        case LOG_DEBUG:
            level_string = "DEBUG |";
            break;
        default:
            break;
    }

    sprintf_s(buffer, sizeof(buffer), "%s %s\n", level_string, msg);
    length = strlen(buffer);
    ret = WriteFile(handle, buffer, length, &writtenBytes, NULL);
    if (!ret) {
        return BASE_LOG_FAILED;
    }
    return BASE_SUCCEED;
}